home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK1.toast / Development Kits (Disc 1) / QuickTime / Programming Stuff / QuickTime 2.1 for Developers / Sprite Sample Code / UseSpriteToolbox.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-19  |  9.2 KB  |  367 lines  |  [TEXT/MMCC]

  1. /*
  2.     SpriteToolBoxSampleCode.c
  3.  
  4.     This sample code shows how the sprite toolbox may be used by an
  5.     application to create a simple sprite animation (one which is
  6.     not contained in a QuickTime movie ).
  7.     
  8. */
  9. #include <Fonts.h>
  10. #include <Movies.h>
  11.  
  12. void CreateSpriteStuff( Rect *windowBounds );
  13. void CreateSprites( void );
  14. void MoveSprites( void );
  15. void DisposeEverything( void );
  16.  
  17. OSErr ExtractCompressData( PicHandle thePict, Handle *dataOut, ImageDescriptionHandle *idh );
  18. pascal void extractStdPix( PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short flags );
  19. void MakePictTransparent( PicHandle pic, RGBColor *keyColor );
  20.  
  21. // exception handling macros
  22.  
  23. #define        FailIf(a, e)         {if (a)     { err = e; goto bail; }}
  24. #define        FailOSErr(a)         {if (err = a)     goto bail;}
  25. #define        FailMemErr(a)        {a; if (err = MemError()) goto bail;}
  26.  
  27. // constants
  28. #define        kNumSprites                4
  29. #define        kNumSpaceShipImages        24        
  30.  
  31. #define        kBackgroundPictID        158
  32. #define        kFirstSpaceShipPictID    (kBackgroundPictID + 1)
  33.  
  34. #define        kSpaceShipWidth            106        
  35. #define        kSpaceShipHeight        80        
  36.  
  37. // lots of globals
  38. GWorldPtr                 spritePlane = nil;
  39. SpriteWorld                gSpriteWorld = nil;
  40. Rect                    gBounceBox;
  41.  
  42. Sprite                    gSprites[kNumSprites];
  43. Rect                    gDestRects[kNumSprites];
  44. Point                    gDeltas[kNumSprites];
  45. short                    gCurrentImages[kNumSprites];
  46.  
  47. ImageSequence            gDecompressSeqs[kNumSpaceShipImages];
  48. Handle                    gCompressedPictures[kNumSpaceShipImages];
  49. ImageDescriptionHandle     gImageDescriptions[kNumSpaceShipImages];
  50.  
  51. RGBColor                gBackgroundColor;
  52.  
  53.  
  54. void main( void ) 
  55. {
  56.     Rect         bounds;
  57.     WindowPtr     w;
  58.     
  59.     InitGraf( &qd.thePort );
  60.     InitFonts();
  61.     InitWindows();
  62.     InitMenus();
  63.     TEInit();
  64.     InitDialogs(0L);
  65.     InitCursor();
  66.     MaxApplZone();
  67.  
  68.     EnterMovies();
  69.  
  70.     // create a window
  71.     SetRect( &bounds, 64, 64, 64 + 512, 64 + 480 );
  72.                                 
  73.     w = NewCWindow( nil, &bounds, "\pClick Mouse to Quit", false, 0, (WindowPtr)-1, true, 0 );
  74.     if ( !w ) return;
  75.  
  76.     SetPort( w );
  77.     AlignWindow( w, true,  nil, nil );
  78.  
  79.     CreateSpriteStuff( &bounds );
  80.  
  81.     ShowWindow( w );
  82.     
  83.     while ( ! Button() ) {
  84.         MoveSprites();
  85.         SpriteWorldIdle( gSpriteWorld, 0, 0 );
  86.     }
  87.     
  88.     DisposeEverything();
  89.     DisposeWindow( w );
  90.     
  91.     ExitMovies();
  92. }
  93.  
  94. void CreateSpriteStuff( Rect *windowBounds )
  95. {
  96.     OSErr        err;
  97.     Rect        bounds;
  98.     
  99.     bounds = *windowBounds;
  100.     OffsetRect( &bounds, -bounds.left, -bounds.top );
  101.     gBounceBox = bounds;
  102.     InsetRect( &gBounceBox, 16, 16 );
  103.  
  104.     NewGWorld( &spritePlane, 8, &bounds, nil, nil, useTempMem );
  105.     if ( spritePlane == nil )
  106.         NewGWorld( &spritePlane, 8, &bounds, nil, nil, 0 );
  107.  
  108.     if ( spritePlane ) {
  109.         LockPixels( spritePlane->portPixMap );
  110.             
  111.         gBackgroundColor.red = gBackgroundColor.green = gBackgroundColor.blue = 0;
  112.         
  113.         err = NewSpriteWorld( &gSpriteWorld, (CGrafPtr)qd.thePort, spritePlane, &gBackgroundColor, nil );    
  114.         CreateSprites();            
  115.     }
  116. }
  117.  
  118. void CreateSprites( void )
  119. {
  120.     long             i;
  121.     Handle            compressedData = nil;
  122.     PicHandle        picture;
  123.     CGrafPtr         savePort;
  124.     GDHandle         saveGD;
  125.     OSErr            err;
  126.     RGBColor        keyColor;
  127.     
  128.     SetRect( &gDestRects[0], 132, 132, 132 + kSpaceShipWidth, 132 + kSpaceShipHeight );
  129.     SetRect( &gDestRects[1], 50, 50, 50 + kSpaceShipWidth, 50 + kSpaceShipHeight );
  130.     SetRect( &gDestRects[2], 100, 100, 100 + kSpaceShipWidth, 100 + kSpaceShipHeight );
  131.     SetRect( &gDestRects[3], 130, 130, 130 + kSpaceShipWidth, 130 + kSpaceShipHeight );        
  132.  
  133.     gDeltas[0].h = -3;
  134.     gDeltas[0].v = 0;
  135.     gDeltas[1].h = -5;
  136.     gDeltas[1].v = 3;
  137.     gDeltas[2].h = 4;
  138.     gDeltas[2].v = -6;
  139.     gDeltas[3].h = 6;
  140.     gDeltas[3].v = 4;
  141.     
  142.     gCurrentImages[0] = 0;
  143.     gCurrentImages[1] = kNumSpaceShipImages / 4;
  144.     gCurrentImages[2] = kNumSpaceShipImages / 2;
  145.     gCurrentImages[3] = kNumSpaceShipImages * 4 / 3;
  146.     
  147.     keyColor.red = keyColor.green = keyColor.blue = 0xFFFF;
  148.     
  149.     // recompress PICTS
  150.     for ( i = 0; i < kNumSpaceShipImages; i++ ) {
  151.         picture = (PicHandle) GetPicture( i + kFirstSpaceShipPictID );
  152.         DetachResource( (Handle)picture );
  153.         
  154.         MakePictTransparent( picture, &keyColor );
  155.         ExtractCompressData( picture, &gCompressedPictures[i], &gImageDescriptions[i] );
  156.         HLock( gCompressedPictures[i] );
  157.         
  158.         KillPicture( picture );
  159.     }
  160.  
  161.     // create the sprites for our sprite world
  162.     for ( i = 0; i < kNumSprites; i++ ) {
  163.         MatrixRecord    matrix;
  164.         
  165.         SetIdentityMatrix( &matrix );
  166.         
  167.         matrix.matrix[2][0] = ((long)gDestRects[i].left << 16);
  168.         matrix.matrix[2][1] = ((long)gDestRects[i].top << 16);
  169.  
  170.         err = NewSprite( &(gSprites[i]), gSpriteWorld, gImageDescriptions[0], *gCompressedPictures[0], &matrix, true, i ); 
  171.     }
  172. }
  173.  
  174. void MoveSprites( void )
  175. {
  176.     short            i;
  177.     MatrixRecord    matrix;
  178.     
  179.     SetIdentityMatrix( &matrix );
  180.     
  181.     for ( i = 0; i < kNumSprites; i++ ) {
  182.  
  183.         OffsetRect( &gDestRects[i], gDeltas[i].h, gDeltas[i].v );
  184.         
  185.         if ( (gDestRects[i].right >= gBounceBox.right ) || (gDestRects[i].left <= gBounceBox.left) )
  186.             gDeltas[i].h = -gDeltas[i].h;
  187.         
  188.         if ( (gDestRects[i].bottom >= gBounceBox.bottom ) || (gDestRects[i].top <= gBounceBox.top) )
  189.             gDeltas[i].v = -gDeltas[i].v;
  190.         
  191.         matrix.matrix[2][0] = ((long)gDestRects[i].left << 16);
  192.         matrix.matrix[2][1] = ((long)gDestRects[i].top << 16);
  193.         
  194.         SetSpriteProperty( gSprites[i], kSpritePropertyMatrix, &matrix );
  195.         
  196.         // change the sprites image too
  197.         gCurrentImages[i]++;
  198.         if ( gCurrentImages[i] >= (kNumSpaceShipImages * (i+1)) )
  199.             gCurrentImages[i] = 0;
  200.         SetSpriteProperty( gSprites[i], kSpritePropertyImageDataPtr, *gCompressedPictures[gCurrentImages[i] / (i+1)] );
  201.     }
  202. }
  203.  
  204. void DisposeEverything( void )
  205. {
  206.     short i;
  207.     
  208.     for ( i = 0; i < kNumSprites; i++ ) {
  209.         if ( gCompressedPictures[i] )
  210.             DisposeHandle( gCompressedPictures[i] );
  211.         if ( gImageDescriptions[i] )
  212.             DisposeHandle( (Handle)gImageDescriptions[i] );
  213.         if ( gSprites[i] )
  214.             DisposeSprite( gSprites[i] );
  215.     }
  216.     if ( gSpriteWorld )
  217.         DisposeSpriteWorld( gSpriteWorld );
  218. }
  219.  
  220.  
  221. // the routines below recompress a PICT using the animation compressor
  222.  
  223. typedef struct {
  224.     CGrafPort tempPort;
  225.  
  226.     Handle data;
  227.     ImageDescriptionHandle idh;
  228. } extractPictRecord;
  229.  
  230. #define compressDepth    16
  231. #define compressType    'rle '
  232.  
  233. OSErr ExtractCompressData( PicHandle thePict, Handle *dataOut, ImageDescriptionHandle *idh )
  234. {
  235.     OSErr                err = noErr;
  236.     extractPictRecord     state;
  237.     CQDProcs             procs;
  238.     GrafPtr             savePort;
  239.     Rect                 bounds;
  240.  
  241.     if ( dataOut )
  242.         *dataOut = nil;
  243.     if ( idh )
  244.         *idh = nil;
  245.  
  246.     GetPort( &savePort );
  247.  
  248.     OpenCPort( &state.tempPort );
  249.     SetStdCProcs( &procs );
  250.     procs.newProc1 = (UniversalProcPtr)extractStdPix;
  251.     state.tempPort.grafProcs = &procs;
  252.  
  253.     state.data = nil;
  254.     state.idh = nil;
  255.  
  256.     SetPort( (GrafPtr)&state.tempPort );
  257.     HidePen();
  258.  
  259.     bounds = (**thePict).picFrame;
  260.     DrawPicture(thePict, &bounds);    
  261.  
  262. bail:
  263.     SetPort( savePort );
  264.     CloseCPort( &state.tempPort );
  265.  
  266.     *dataOut    = state.data;
  267.     *idh        = state.idh;
  268.  
  269.     return err;
  270. }
  271.  
  272. pascal void extractStdPix( PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short flags )
  273. {
  274. #pragma unused(srcRect,matrix,mode,mask,matte,matteRect,flags)
  275.     extractPictRecord    *state;
  276.  
  277.     GetPort( (GrafPtr *)&state );
  278.  
  279.     if  ( state->idh == nil ) {
  280.         ImageDescriptionHandle    desc;
  281.         Ptr                     data;
  282.         long                    bufferSize;
  283.  
  284.         if ( GetCompressedPixMapInfo(src, &desc, &data, &bufferSize, nil, nil) == noErr ) {
  285.             state->idh = desc;
  286.             HandToHand( (Handle *)&state->idh );
  287.             PtrToHand( data, &state->data, bufferSize );
  288.         }
  289.     }
  290. }
  291.  
  292. void MakePictTransparent( PicHandle pic, RGBColor *keyColor )
  293. {
  294.     OSErr                    err;
  295.     CGrafPtr                 savePort;
  296.     GDHandle                 saveGD;
  297.     GWorldPtr                 gw = nil;
  298.     Rect                     bounds;
  299.     ImageSequence             seq = 0;
  300.     ImageDescriptionHandle     desc = nil;
  301.     Ptr                     data = 0;
  302.     long                     dataSize;
  303.     UInt8                     similarity;
  304.     PicHandle                 newPict = nil;
  305.     RGBColor                 saveBackColor;
  306.     
  307.     GetGWorld( &savePort, &saveGD );
  308.  
  309.     bounds = (**(PicHandle)pic).picFrame;
  310.     OffsetRect( &bounds, -bounds.left, -bounds.top );
  311.  
  312.     err = NewGWorld( &gw, compressDepth, &bounds, nil, nil, useTempMem );
  313.     if (err)
  314.         err = NewGWorld( &gw, compressDepth, &bounds, nil, nil, 0 );
  315.  
  316.     LockPixels( gw->portPixMap );
  317.     SetGWorld( gw, nil );
  318.  
  319.     GetBackColor( &saveBackColor );
  320.     RGBBackColor( keyColor );
  321.  
  322.         EraseRect( &bounds );
  323.  
  324.     RGBBackColor( &saveBackColor );
  325.  
  326.     desc = (ImageDescriptionHandle)NewHandleClear( sizeof(ImageDescription) );
  327.     if ( err = MemError() ) goto bail;
  328.  
  329.     err = CompressSequenceBegin( &seq, gw->portPixMap, nil, &bounds, nil, compressDepth, compressType, 0, codecMaxQuality, codecMaxQuality, 0, nil, 0, desc );
  330.     if (err) goto bail;
  331.  
  332.     err = GetMaxCompressionSize( gw->portPixMap, &bounds, compressDepth, codecMaxQuality, compressType, 0, &dataSize );
  333.     if ( err ) goto bail;
  334.  
  335.     data = NewPtr( dataSize );
  336.     if ( err = MemError() ) goto bail;
  337.  
  338.     err = CompressSequenceFrame( seq, gw->portPixMap, &bounds, codecFlagUpdatePrevious, data, &dataSize, &similarity, nil );
  339.     if ( err ) goto bail;
  340.  
  341.     DrawPicture( pic, &bounds );
  342.  
  343.     err = CompressSequenceFrame( seq, gw->portPixMap, &bounds, codecFlagUpdatePrevious, data, &dataSize, &similarity, nil );
  344.     if ( err ) goto bail;
  345.  
  346.     CDSequenceEnd( seq );
  347.     seq = 0;
  348.  
  349.     newPict =  OpenPicture( &bounds );
  350.     err = DecompressImage( data, desc, gw->portPixMap, &bounds, &bounds, ditherCopy, nil );
  351.     ClosePicture();
  352.     if ( err ) goto bail;
  353.  
  354.     SetHandleSize( (Handle)pic, 0 );
  355.     HandAndHand( (Handle)newPict, (Handle)pic );
  356.  
  357. bail:
  358.     CDSequenceEnd( seq );
  359.     SetGWorld( savePort, saveGD );
  360.     if ( gw ) DisposeGWorld( gw );
  361.     DisposeHandle( (Handle)desc );
  362.     if ( data ) DisposePtr( data );
  363.     KillPicture( newPict );
  364.  
  365.     return;
  366. }
  367.